//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <engine.h>

ECode CGrafixSurface::Blit(
    /* [in] */ CGrafixSurface* source,
    /* [in] */ Rectangle srcRectangle,
    /* [in] */ Int32 destX,
    /* [in] */ Int32 destY,
    /* [in] */ UInt32 color)
{
    assert(source);

    Buffer* srcBuffer = &source->m_cacheBuffer->m_buffer;
    Buffer* dstBuffer = &m_cacheBuffer->m_buffer;
    UInt8 opacity = 0xFF;

    assert(srcBuffer != dstBuffer);

    assert(m_format == dstBuffer->info.pixelFormat
        && source->m_format == srcBuffer->info.pixelFormat);

    assert((PixelFormat_ARGB == srcBuffer->info.pixelFormat
            || PixelFormat_RGB24 == srcBuffer->info.pixelFormat
            || PixelFormat_A8 == srcBuffer->info.pixelFormat)
        && (PixelFormat_ARGB == dstBuffer->info.pixelFormat
            || PixelFormat_RGB24 == dstBuffer->info.pixelFormat));

    assert(BITS_PER_PIXEL(dstBuffer->info.pixelFormat) == dstBuffer->info.bitsPerPixel);
    assert(BITS_PER_PIXEL(srcBuffer->info.pixelFormat) == srcBuffer->info.bitsPerPixel);

    if (source->m_grafixObject) {
        assert(0xFF == source->m_grafixObject->m_config.opacity
            || (source->m_grafixObject->m_config.option
                & GrafixAttribute_AlphaChannel));
        opacity = source->m_grafixObject->m_config.opacity;
    }

    if (PixelFormat_ARGB == srcBuffer->info.pixelFormat) {
        if (PixelFormat_ARGB == dstBuffer->info.pixelFormat) {
            ARGB32Blit2ARGB32(
                    dstBuffer->info.address,
                        destX, destY, dstBuffer->info.pitch,
                    srcBuffer->info.address,
                        srcRectangle.x, srcRectangle.y,
                        srcRectangle.width, srcRectangle.height,
                        srcBuffer->info.pitch,
                    opacity);
        }
        else {
            assert(PixelFormat_RGB24 == dstBuffer->info.pixelFormat);
            ARGB32Blit2RGB24(
                    dstBuffer->info.address,
                        destX, destY, dstBuffer->info.pitch,
                    srcBuffer->info.address,
                        srcRectangle.x, srcRectangle.y,
                        srcRectangle.width, srcRectangle.height,
                        srcBuffer->info.pitch,
                    opacity);
        }
    }
    else {
        if (PixelFormat_ARGB == dstBuffer->info.pixelFormat) {
            RGB24Blit2ARGB32(
                    dstBuffer->info.address,
                        destX, destY, dstBuffer->info.pitch,
                    srcBuffer->info.address,
                        srcRectangle.x, srcRectangle.y,
                        srcRectangle.width, srcRectangle.height,
                        srcBuffer->info.pitch,
                    opacity);
        }
        else {
            assert(PixelFormat_RGB24 == dstBuffer->info.pixelFormat);
            RGB24Blit2RGB24(
                    dstBuffer->info.address,
                        destX, destY, dstBuffer->info.pitch,
                    srcBuffer->info.address,
                        srcRectangle.x, srcRectangle.y,
                        srcRectangle.width, srcRectangle.height,
                        srcBuffer->info.pitch,
                    opacity);
        }
    }

    return NOERROR;
}

//ECode CGrafixSurface::Blit(
//    /* [in] */ CGrafixSurface* source,
//    /* [in] */ Rectangle srcRectangle,
//    /* [in] */ Int32 destX,
//    /* [in] */ Int32 destY,
//    /* [in] */ UInt32 color)
//{
//    assert(source);
//
//    Buffer* srcBuffer = &source->m_cacheBuffer->m_buffer;
//    Buffer* dstBuffer = &m_cacheBuffer->m_buffer;
//    GrafixAttribute attribute = source->m_attribute;
//
//    assert(!source->m_grafixObject || source->m_grafixObject->m_config.option == attribute);
//
//    if (srcBuffer == dstBuffer) {
//        GFX_EXPRESSION(ERRORLEVEL,
//            kprintf("The source surface is as same as the destination\n"));
//
//        return E_INVALID_ARGUMENT;
//    }
//
//    assert(m_format == dstBuffer->info.pixelFormat
//        && source->m_format == srcBuffer->info.pixelFormat);
//
//    assert((PixelFormat_ARGB == srcBuffer->info.pixelFormat
//            || PixelFormat_RGB24 == srcBuffer->info.pixelFormat
//            || PixelFormat_A8 == srcBuffer->info.pixelFormat)
//        && (PixelFormat_ARGB == dstBuffer->info.pixelFormat
//            || PixelFormat_RGB24 == dstBuffer->info.pixelFormat));
//
//    assert(BITS_PER_PIXEL(dstBuffer->info.pixelFormat) == dstBuffer->info.bitsPerPixel);
//    assert(BITS_PER_PIXEL(srcBuffer->info.pixelFormat) == srcBuffer->info.bitsPerPixel);
//
//    Region srcRegion = REGION_INIT_FROM_RECTANGLE(&srcRectangle);
//    Rectangle srcRect;
//
//    UInt32 srcPitch = srcBuffer->info.pitch;
//    UInt32 dstPitch = dstBuffer->info.pitch;
//
//    UInt8* srcBegin;
//    UInt8* dstBegin;
//
//    UInt32 srcBpp = srcBuffer->info.bitsPerPixel >> 3;
//    UInt32 dstBpp = dstBuffer->info.bitsPerPixel >> 3;
//
//    UInt32 height;
//    UInt32 width;
//
//    UInt32 winAlpha = 0xFF;
//
//    BlitControl options = BlitControl_AlphaPixel;
//
//    UInt8 alpha = 0, red = 0, green = 0, blue = 0;
//
//    if (source->m_grafixObject
//            && (attribute & GrafixAttribute_AlphaChannel)
//            && source->m_grafixObject->m_config.opacity) {
//        winAlpha = source->m_grafixObject->m_config.opacity;
//        options = BlitControl_AlphaChannel;
//        if (0 == winAlpha) {
//            goto Exit;
//        }
//    }
//
//#ifdef _DEBUG
//    if (PixelFormat_ARGB == srcBuffer->info.pixelFormat) {
//        assert(attribute & GrafixAttribute_AlphaPixel);
//    }
//    else {
//        assert(!(attribute & GrafixAttribute_AlphaPixel));
//        assert(PixelFormat_RGB24 == srcBuffer->info.pixelFormat
//            || PixelFormat_A8 == srcBuffer->info.pixelFormat);
//    }
//#endif
//
//    if (BlitControl_AlphaPixel == options
//            && PixelFormat_RGB24 == srcBuffer->info.pixelFormat
//            && PixelFormat_RGB24 == dstBuffer->info.pixelFormat) {
//        options = BlitControl_Normal;
//    }
//
//    if (PixelFormat_A8 == srcBuffer->info.pixelFormat
//            && PixelFormat_A8 != dstBuffer->info.pixelFormat) {
//        assert(!source->m_grafixObject);
//        assert(BlitControl_AlphaPixel == options);
//        options = BlitControl_A8;
//        if (COLOR_TRANSPARENT == color) {
//            goto Exit;
//        }
//
//        alpha = color >> 24;
//        if (0xFF == alpha) {
//            red = (color & 0x00FF0000) >> 16;
//            green = (color & 0x0000FF00) >> 8;
//            blue = color & 0x000000FF;
//        }
//        else if (0 == alpha ) {
//            red = green = blue = 0;
//        }
//        else {
//            red = (((color & 0x00FF0000) >> 8) / alpha) & 0x000000FF;
//            green = ((color & 0x0000FF00) / alpha) & 0x000000FF;
//            blue = (((color & 0x000000FF) << 8) / alpha) & 0x000000FF;
//        }
//    }
//
//    RectangleFromRegion(&srcRect, &srcRegion);
//
//    srcBegin = (UInt8 *)srcBuffer->info.address
//                + srcRect.y * srcPitch
//                + srcRect.x * srcBpp;
//
//    dstBegin = (UInt8 *)dstBuffer->info.address
//                + destY * dstPitch
//                + destX * dstBpp;
//
//    height = srcRect.height;
//    width = srcRect.width;
//
//    while (height--) {
//        switch (options) {
//        case BlitControl_Normal: {
//            memcpy(dstBegin, srcBegin, width * srcBpp);
//
//            break;
//        }
//
//        case BlitControl_AlphaChannel:
//        case BlitControl_AlphaPixel: {
//            UInt32* src = (UInt32 *)srcBegin;
//            UInt32* dst = (UInt32 *)dstBegin;
//            UInt32 w = width;
//
//            if (PixelFormat_ARGB == dstBuffer->info.pixelFormat) {
//                assert(m_attribute & GrafixAttribute_AlphaPixel);
//                assert(!m_grafixObject
//                || m_grafixObject->m_config.option & GrafixAttribute_AlphaPixel);
//                if (PixelFormat_ARGB == srcBuffer->info.pixelFormat) {
//                    while (w--) {
//                        *dst = ARGBBlentARGB(*dst, *src, winAlpha);
//
//                        src++;
//                        dst++;
//                    }
//                }
//                else {
//                    while (w--) {
//                        *dst = ARGBBlentRGB24(*dst, *src, winAlpha);
//
//                        src++;
//                        dst++;
//                    }
//                }
//            }
//            else {
//                assert(PixelFormat_RGB24 == dstBuffer->info.pixelFormat);
//                if (PixelFormat_ARGB == srcBuffer->info.pixelFormat) {
//                    while (w--) {
//                        *dst = RGB24BlentARGB(*dst, *src, winAlpha);
//
//                        src++;
//                        dst++;
//                    }
//                }
//                else {
//                    while (w--) {
//                        *dst = RGB24BlentRGB24(*dst, *src, winAlpha);
//
//                        src++;
//                        dst++;
//                    }
//                }
//            }
//
//            break;
//        }
//
//        case BlitControl_A8: {
//            assert(PixelFormat_A8 == srcBuffer->info.pixelFormat);
//
//            UInt8* src = (UInt8 *)srcBegin;
//            UInt32* dst = (UInt32 *)dstBegin;
//            UInt32 w = width;
//
//            if (PixelFormat_ARGB == dstBuffer->info.pixelFormat) {
//                if (0xFF == alpha) {
//                    while (w--) {
//                        UInt8 a8 = *src;
//
//                        if (a8) {
//                            *dst = ARGBBlentARGB(*dst,
//                                ARGB2Color(a8, red, green, blue));
//                        }
//
//                        dst++;
//                        src++;
//                    }
//                }
//                else {
//                    while (w--) {
//                        UInt8 a8 = *src;
//
//                        if (a8) {
//                            *dst = ARGBBlentARGB(*dst,
//                                ARGB2Color((a8 * alpha) >> 8,
//                                        red, green, blue));
//                        }
//
//                        dst++;
//                        src++;
//                    }
//                }
//            }
//            else {
//                if (0xFF == alpha) {
//                    while (w--) {
//                        UInt8 a8 = *src;
//
//                        if (a8) {
//                            *dst = RGB24BlentARGB(*dst,
//                                ARGB2Color(a8, red, green, blue));
//                        }
//
//                        dst++;
//                        src++;
//                    }
//                }
//                else {
//                    while (w--) {
//                        UInt8 a8 = *src;
//
//                        if (a8) {
//                            *dst = RGB24BlentARGB(*dst,
//                                ARGB2Color((a8 * alpha) >> 8,
//                                        red, green, blue));
//                        }
//
//                        dst++;
//                        src++;
//                    }
//                }
//            }
//
//            break;
//        }
//
//        default: {
//            GFX_EXPRESSION(ERRORLEVEL,
//                kprintf("Unknown the operation\n"));
//
//            return E_INVALID_OPERATION;
//        }
//        }
//
//        dstBegin += dstPitch;
//        srcBegin += srcPitch;
//    }
//
//Exit:
//    return NOERROR;
//}

ECode CGrafixSurface::StretchBlit(
    /* [in] */ CGrafixSurface* source,
    /* [in] */ Rectangle sourceRectangle,
    /* [in] */ Rectangle destinationRectangle,
    /* [in] */ UInt32 color,
    /* [in] */ Boolean layerChannel)
{
    assert(source);

    assert(0);

//    Buffer* srcBuffer = &source->m_cacheBuffer->m_buffer;
//    Buffer* dstBuffer = &m_cacheBuffer->m_buffer;
//
//    assert(!source->m_grafixObject
//        || source->m_grafixObject->m_config.option == source->m_attribute);
//
//    if (srcBuffer == dstBuffer) {
//        GFX_EXPRESSION(ERRORLEVEL,
//            kprintf("The source surface is as same as the destination\n"));
//
//        return E_INVALID_ARGUMENT;
//    }
//
//    assert(m_format == dstBuffer->info.pixelFormat
//        && source->m_format == srcBuffer->info.pixelFormat);
//
//    assert((PixelFormat_ARGB == srcBuffer->info.pixelFormat
//            || PixelFormat_RGB24 == srcBuffer->info.pixelFormat
//            || PixelFormat_A8 == srcBuffer->info.pixelFormat)
//        && (PixelFormat_ARGB == dstBuffer->info.pixelFormat
//            || PixelFormat_RGB24 == dstBuffer->info.pixelFormat));
//
//    assert(BITS_PER_PIXEL(dstBuffer->info.pixelFormat) == dstBuffer->info.bitsPerPixel);
//    assert(BITS_PER_PIXEL(srcBuffer->info.pixelFormat) == srcBuffer->info.bitsPerPixel);
//
//    Rectangle srcRect = sourceRectangle;
//    Rectangle dstRect = destinationRectangle;
//
//    UInt32 srcPitch = srcBuffer->info.pitch;
//    UInt32 dstPitch = dstBuffer->info.pitch;
//
//    UInt8* srcBegin;
//    UInt8* dstBegin;
//
//    UInt32 srcBpp = srcBuffer->info.bitsPerPixel >> 3;
//    UInt32 dstBpp = dstBuffer->info.bitsPerPixel >> 3;
//
//    UInt32 integerX = sourceRectangle.width / destinationRectangle.width;
//    UInt32 residueX = sourceRectangle.width % destinationRectangle.width;
//    Int32 decimalX = 0;
//
//    UInt32 integerY = sourceRectangle.height / destinationRectangle.height;
//    UInt32 residueY = sourceRectangle.height % destinationRectangle.height;
//    Int32 decimalY = 0;
//
//    UInt32 height;
//    UInt32 width;
//
//    BlitControl options = BlitControl_AlphaPixel;
//
//    UInt8 alpha = 0, red = 0, green = 0, blue = 0;
//
//    if (PixelFormat_RGB24 == srcBuffer->info.pixelFormat
//            && PixelFormat_RGB24 == dstBuffer->info.pixelFormat) {
//        options = BlitControl_Normal;
//    }
//
//    if (PixelFormat_A8 == srcBuffer->info.pixelFormat
//            && PixelFormat_A8 != dstBuffer->info.pixelFormat) {
//        assert(!source->m_grafixObject);
//        assert(BlitControl_Normal == options);
//        options = BlitControl_A8;
//        if (COLOR_TRANSPARENT == color) {
//            return NOERROR;
//        }
//
//        alpha = color >> 24;
//        if (0xFF == alpha) {
//            red = (color & 0x00FF0000) >> 16;
//            green = (color & 0x0000FF00) >> 8;
//            blue = color & 0x000000FF;
//        }
//        else if (0 == alpha ) {
//            red = green = blue = 0;
//        }
//        else {
//            red = (((color & 0x00FF0000) >> 8) / alpha) & 0x000000FF;
//            green = ((color & 0x0000FF00) / alpha) & 0x000000FF;
//            blue = (((color & 0x000000FF) << 8) / alpha) & 0x000000FF;
//        }
//    }
//
//    srcBegin = (UInt8 *)srcBuffer->info.address
//                + srcRect.y * srcPitch
//                + srcRect.x * srcBpp;
//
//    dstBegin = (UInt8 *)dstBuffer->info.address
//                + dstRect.y * dstPitch
//                + dstRect.x * dstBpp;
//
//    height = dstRect.height;
//    width = dstRect.width;
//
//    while (height--) {
//        switch (options) {
//        case BlitControl_Normal: {
//            UInt32 w = width;
//            UInt32* src = (UInt32 *)srcBegin;
//            UInt32* dst = (UInt32 *)dstBegin;
//
//            while (w--) {
//                *dst = *src;
//
//                dst++;
//
//                src += integerX;
//                decimalX += residueX;
//                if (decimalX >= destinationRectangle.width) {
//                    src += 1;
//                    decimalX -= destinationRectangle.width;
//                }
//            }
//
//            break;
//        }
//
//        case BlitControl_AlphaPixel: {
//            UInt32* src = (UInt32 *)srcBegin;
//            UInt32* dst = (UInt32 *)dstBegin;
//            UInt32 w = width;
//
//            if (PixelFormat_ARGB == dstBuffer->info.pixelFormat) {
//                assert(m_attribute & GrafixAttribute_AlphaPixel);
//                assert(!m_grafixObject
//                || m_grafixObject->m_config.option & GrafixAttribute_AlphaPixel);
//                if (PixelFormat_ARGB == srcBuffer->info.pixelFormat) {
//                    while (w--) {
//                        *dst = ARGBBlentARGB(*dst, *src);
//
//                        dst++;
//
//                        src += integerX;
//                        decimalX += residueX;
//                        if (decimalX >= destinationRectangle.width) {
//                            src += 1;
//                            decimalX -= destinationRectangle.width;
//                        }
//                    }
//                }
//                else {
//                    while (w--) {
//                        *dst = ARGBBlentRGB24(*dst, *src);
//
//                        dst++;
//
//                        src += integerX;
//                        decimalX += residueX;
//                        if (decimalX >= destinationRectangle.width) {
//                            src += 1;
//                            decimalX -= destinationRectangle.width;
//                        }
//                    }
//                }
//            }
//            else {
//                assert(PixelFormat_RGB24 == dstBuffer->info.pixelFormat);
//                if (PixelFormat_ARGB == srcBuffer->info.pixelFormat) {
//                    while (w--) {
//                        *dst = RGB24BlentARGB(*dst, *src);
//
//                        dst++;
//
//                        src += integerX;
//                        decimalX += residueX;
//                        if (decimalX >= destinationRectangle.width) {
//                            src += 1;
//                            decimalX -= destinationRectangle.width;
//                        }
//                    }
//                }
//                else {
//                    while (w--) {
//                        *dst = RGB24BlentRGB24(*dst, *src);
//
//                        dst++;
//
//                        src += integerX;
//                        decimalX += residueX;
//                        if (decimalX >= destinationRectangle.width) {
//                            src += 1;
//                            decimalX -= destinationRectangle.width;
//                        }
//                    }
//                }
//            }
//
//            break;
//        }
//
//        case BlitControl_A8:{
//            assert(PixelFormat_A8 == srcBuffer->info.pixelFormat);
//
//            UInt8* src = (UInt8 *)srcBegin;
//            UInt32 w = width;
//            UInt32* dst = (UInt32 *)dstBegin;
//
//            if (PixelFormat_ARGB == dstBuffer->info.pixelFormat) {
//                if (0xFF == alpha) {
//                    while (w--) {
//                        UInt8 a8 = *src;
//
//                        if (a8) {
//                            *dst = ARGBBlentARGB(*dst,
//                                ARGB2Color(a8, red, green, blue));
//                        }
//
//                        dst++;
//
//                        src += integerX;
//                        decimalX += residueX;
//                        if (decimalX >= destinationRectangle.width) {
//                            src += 1;
//                            decimalX -= destinationRectangle.width;
//                        }
//                    }
//                }
//                else {
//                    while (w--) {
//                        UInt8 a8 = *src;
//
//                        if (a8) {
//                            *dst = ARGBBlentARGB(*dst,
//                                ARGB2Color((a8 * alpha) >> 8,
//                                        red, green, blue));
//                        }
//
//                        dst++;
//
//                        src += integerX;
//                        decimalX += residueX;
//                        if (decimalX >= destinationRectangle.width) {
//                            src += 1;
//                            decimalX -= destinationRectangle.width;
//                        }
//                    }
//                }
//            }
//            else {
//                if (0xFF == alpha) {
//                    while (w--) {
//                        UInt8 a8 = *src;
//
//                        if (a8) {
//                            *dst = RGB24BlentARGB(*dst,
//                                ARGB2Color(a8, red, green, blue));
//                        }
//
//                        dst++;
//
//                        src += integerX;
//                        decimalX += residueX;
//                        if (decimalX >= destinationRectangle.width) {
//                            src += 1;
//                            decimalX -= destinationRectangle.width;
//                        }
//                    }
//                }
//                else {
//                    while (w--) {
//                        UInt8 a8 = *src;
//
//                        if (a8) {
//                            *dst = RGB24BlentARGB(*dst,
//                                ARGB2Color((a8 * alpha) >> 8,
//                                        red, green, blue));
//                        }
//
//                        dst++;
//
//                        src += integerX;
//                        decimalX += residueX;
//                        if (decimalX >= destinationRectangle.width) {
//                            src += 1;
//                            decimalX -= destinationRectangle.width;
//                        }
//                    }
//                }
//            }
//
//            break;
//        }
//
//        default:{
//            GFX_EXPRESSION(ERRORLEVEL,
//                kprintf("Unknown the operation\n"));
//
//            return E_INVALID_OPERATION;
//        }
//        }
//
//        dstBegin += dstPitch;
//
//        srcBegin += srcPitch * integerY;
//        decimalY += residueY;
//        if (decimalY >= destinationRectangle.height) {
//            srcBegin += srcPitch;
//            decimalY -= destinationRectangle.height;
//        }
//    }

    return NOERROR;
}


